package cup;

//import java_cup.runtime.*;
import command.*;
import base.*;
import utilities.*;

/**
 * This class is a simple example lexer.
 */
%%

%class SoloCommandScanner
%unicode
%column
%line
%public
%type Command

%eofval{
throw new java.io.EOFException();
%eofval}

%{
  StringBuffer string = new StringBuffer();
  Command command;
  Criterion criterion;
  int key_len;
  File file;

%}



Identifier = [_.a-zA-Z0-9]*
Key = [a-z0-9]{32}

DecIntegerLiteral = 0 | [1-9][0-9]*
look_value = {Identifier} | {DecIntegerLiteral}


%state STRING
%state FAKEEND
%state YYINITIAL      
%state LISTEN        
%state ANPORT       
%state SEED        
%state SEED_RB    
%state SEED_FILENAME
%state SEED_LENGHT 
%state SEED_PIECE_SIZE 
%state SEED_KEY       
%state LEECH         
%state LEECH_RB     
%state LEECH_KEY
%state LOOK_LB 
%state LOOK_CRITERION
%state LOOK_VALUE
%state LOOK_OPERATOR
%state GKEY
%state USEED
%state USEED_RB
%state USEED_KEY
%state ULEECH
%state ULEECH_RB
%state ULEECH_KEY

%%

/* announce command */

<YYINITIAL>         "announce"             {command = new AnnounceCommand(); yybegin(LISTEN);}
<LISTEN>            "listen"               {yybegin(ANPORT);}
<ANPORT>            {DecIntegerLiteral}    {command.setPort(Integer.parseInt(yytext())); yybegin(SEED);}
<SEED>              "seed"                 {yybegin(SEED_RB);}
<SEED_RB>           \[                     {yybegin(SEED_FILENAME);}


<SEED_FILENAME>{
                    \]                     {yybegin(LEECH);}
                    {Identifier}           {file = new File(); file.setFilenameTmp(yytext());yybegin(SEED_LENGHT);}
}
<SEED_LENGHT>       {DecIntegerLiteral}    {file.setFileLength(Integer.parseInt(yytext())) ; yybegin(SEED_PIECE_SIZE);}
<SEED_PIECE_SIZE>   {DecIntegerLiteral}    {file.setFilePieceSize(Integer.parseInt(yytext())) ; key_len = 0; yybegin(SEED_KEY);}
/*<SEED_KEY>          {KeyChar}              {key_len++; yybegin(SEED_KEY);}*/
<SEED_KEY>          {Key}                  {file.setKey(yytext()); ((AnnounceCommand) command).addSeedFile(file) ; yybegin(SEED_FILENAME);}


<LEECH>             "leech"                {yybegin(LEECH_RB);}
<LEECH_RB>          \[                     {yybegin(LEECH_KEY);}
<LEECH_KEY>{
                    \]                     {yybegin(YYINITIAL);return command;}
                    {Key}                  {((AnnounceCommand) command).addLeechKey(yytext());}
}



/*getfile*/
<YYINITIAL>         "getfile"             {command = new GetFileCommand(); yybegin(GKEY);}
<GKEY>              {Key}                 {((GetFileCommand) command).setKey(yytext()); yybegin(YYINITIAL); return command; }



/*look*/
<YYINITIAL>         "look"             {command = new LookCommand(); yybegin(LOOK_LB);}
<LOOK_LB>           \[                 {yybegin(LOOK_CRITERION); }
<LOOK_CRITERION>{           
                    \]                 {yybegin(YYINITIAL);return command;}
                    "filename"         {criterion = new Criterion(); criterion.setParam(Criterion.Choice.FILENAME);yybegin(LOOK_OPERATOR);}
                    "filesize"         {criterion = new Criterion(); criterion.setParam(Criterion.Choice.FILESIZE);yybegin(LOOK_OPERATOR);}
}
<LOOK_OPERATOR>{
                    "="                {criterion.setOperator(Criterion.Operator.EQ); yybegin(LOOK_VALUE);}
                    "<="               {criterion.setOperator(Criterion.Operator.LEQ);yybegin(LOOK_VALUE);}
                    "<"                {criterion.setOperator(Criterion.Operator.L);yybegin(LOOK_VALUE);}
                    ">"                {criterion.setOperator(Criterion.Operator.G);yybegin(LOOK_VALUE);}
                    ">="               {criterion.setOperator(Criterion.Operator.GEQ);yybegin(LOOK_VALUE);}
}
<LOOK_VALUE>        \"{look_value}\"   {criterion.setValue(yytext().substring(1, yytext().length()-1)); ((LookCommand) command).addCriterion(criterion) ;yybegin(LOOK_CRITERION);}




<YYINITIAL>         "update"             {command = new UpdateCommand(); yybegin(USEED);}
<USEED>             "seed"               {yybegin(USEED_RB);}
<USEED_RB>           \[                  {yybegin(USEED_KEY);}


<USEED_KEY>{
                    \]                     {yybegin(ULEECH);}
                    {Key}                  {((UpdateCommand) command).addSeedKey(yytext());}
}
<ULEECH>            "leech"                {yybegin(ULEECH_RB);}
<ULEECH_RB>          \[                    {yybegin(ULEECH_KEY);}
<ULEECH_KEY>{
                    \]                     {yybegin(YYINITIAL);return command;}
                    {Key}                  {((UpdateCommand) command).addLeechKey(yytext());}
}




/*
<YYINITIAL> "getfile"           { return symbol(sym.GETFILE); }
<YYINITIAL> "look"           { return symbol(sym.GETFILE); }

<YYINITIAL> "listen"            { return symbol(sym.LISTEN); }
<YYINITIAL> "seed"              { return symbol(sym.SEED); }
<YYINITIAL> "leech"             { return symbol(sym.LEECH); }

<YYINITIAL> {
  {Identifier}                   { return symbol(sym.IDENTIFIER, yytext()); }
  
 
  {DecIntegerLiteral}            { return symbol(sym.INTEGER_LITTERAL, Integer.parseInt(yytext()));}
  \"                             { string.setLength(0); yybegin(STRING); }

  "="                            { return symbol(sym.EQ); }
  ">="                           { return symbol(sym.GEQ); }
  "<="                           { return symbol(sym.LEQ); }

  "]"                            { return symbol(sym.RB); }
  "["                            { return symbol(sym.LB); }

//whitespace
  " "                            { }
  \n                             { }
}

<STRING> {
  \"                             { yybegin(YYINITIAL); 
                                   return symbol(sym.STRING, 
                                   string.toString()); }
  [^\n\r\"\\]+                   { string.append( yytext() ); }
  \\t                            { string.append('\t'); }
  \\n                            { string.append('\n'); }

  \\r                            { string.append('\r'); }
  \\\"                           { string.append('\"'); }
  \\                             { string.append('\\'); }
}

<FAKEEND> {
  .|\n                              {yybegin(YYINITIAL);}
}
*/

/*ignore whitespaces*/
" " { }
"\n"  { }

/* error fallback */
.                             { throw new Error("Illegal character <" + yytext()+">"); }

